package com.hp.bon.sgw.wkflow;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.gadberry.utility.expression.Argument;
import com.gadberry.utility.expression.ArgumentCastException;
import com.gadberry.utility.expression.Expression;
import com.gadberry.utility.expression.InvalidExpressionException;
import com.hp.bon.sgw.ctrl.VarFether;
import com.hp.bon.sgw.wkflow.impl.CardPingAreaCodeVarObj;
import com.hp.bon.sgw.wkflow.impl.ComReqSerialGen;
import com.hp.bon.sgw.wkflow.impl.ComTimeVarObj;
import com.hp.bon.sgw.wkflow.impl.FixLengthStrFuncVarObj;

public class FlowExpressionParser extends VarFether {
	/**
	 * 所有定义的流程相关FlowVarObj
	 */
	protected Map<String, FlowVarObj> allFlowVarObjs = new ConcurrentHashMap<String, FlowVarObj>();
	/**
	 * 流程定义的所有变量
	 */
	private Map<String, Object> allFlowVars = new ConcurrentHashMap<String, Object>();

	static Map<String, FlowVarObj> staticFlowVarObjs = new HashMap<String, FlowVarObj>();

	static {
		staticFlowVarObjs.put("cardPin2AreaCode", new CardPingAreaCodeVarObj());
		staticFlowVarObjs.put("comReqSerialGen", new ComReqSerialGen());
		staticFlowVarObjs.put("comCurTime", new ComTimeVarObj());
		staticFlowVarObjs.put("comFixLenStr", new FixLengthStrFuncVarObj());
	}

	public FlowExpressionParser() {
		allFlowVarObjs.putAll(staticFlowVarObjs);
	}

	/**
	 * 得到某个变量
	 * 
	 * @param varName
	 * @return
	 */
	public Object getVar(String varName) {
		Object value = allFlowVars.get(varName);
		if (value != null) {
			return value;
		} else {
			return this.allFlowVarObjs.get(varName);
		}
	}

	public String evalExpression(String expr) throws InvalidExpressionException {
		String varReplacedExpr = replaceVars(expr);
		return Expression.evaluate(varReplacedExpr).toString();
	}

	public boolean evalCond(String expr) throws ArgumentCastException, InvalidExpressionException {
		String varReplacedExpr = replaceVars(expr);
		Argument argm = Expression.evaluate(varReplacedExpr);
		if (argm.isBoolean()) {
			return argm.toBoolean();
		} else {
			return false;
		}
	}

	public String replaceVars(String expr) {
		return replaceVars(expr, this);
	}

	public static String replaceVars(String expr, VarFether varFecher) {
		StringBuilder sb = new StringBuilder();
		int preDollarPos = -2;
		boolean maybeVar = false;
		StringBuilder varBuf = new StringBuilder();
		StringBuilder temp = new StringBuilder();
		for (int i = 0; i < expr.length(); i++) {
			char ch = expr.charAt(i);
			if (maybeVar) {
				if (ch == '}') {
					String varName = varBuf.toString();
					sb.append(varFecher.getVarValue(varName));
					maybeVar = false;
					varBuf.delete(0, varBuf.length());
					temp.delete(0, temp.length());
				} else {
					varBuf.append(ch);
					temp.append(ch);
				}

			} else {// not var
				if (ch == '{') {
					if (preDollarPos + 1 == i) {
						// 可能是 ${的变量定义开始
						maybeVar = true;
						temp.append(ch);
					} else {//
						// 以前缓存的部分
						sb.append(temp.toString());
						temp.delete(0, temp.length());
						sb.append(ch);

					}
				} else if (ch == '$') {
					preDollarPos = i;
					temp.append(ch);
				} else {
					sb.append(ch);
				}
			}

		}
		// 是否有遗留的temp内容
		sb.append(temp.toString());
		return sb.toString();
	}

	private Object getFlowVarObj(String varName) {
		int indx = varName.indexOf(".");
		String objName = varName;
		String propName = null;
		if (indx > 0) {
			objName = varName.substring(0, indx);
			propName = varName.substring(indx + 1);

		}
		FlowVarObj flowVarObj = allFlowVarObjs.get(objName);
		if (flowVarObj == null) {
			throw new RuntimeException("cant't find flow var of name:" + varName + " objName:" + objName);
		}
		return flowVarObj.getProperty(propName);
	}

	/**
	 * @param varName
	 * @return
	 */
	public Object getVarValue(String varName) {
		if (varName.startsWith("$")) {
			// 获取实际变量的值
			String value = (String) allFlowVars.get(varName.substring(1));
			if (value == null) {
				throw new RuntimeException("cant't find var of name:" + varName);
			} else {
				return getFlowVarObj(value);
			}
		} else {
			if (allFlowVars.containsKey(varName)) {
				return allFlowVars.get(varName);
			} else {
				return getFlowVarObj(varName);
			}
		}

	}
	/**
	 * 为复合对象，调用举例：
	 * 1、收到的消息对象，对应"input"
	 * 2、收到的消息DATA，即业务部分，对应"inputdata"
	 * 3、发送的请求、收到的应答消息体，对应在Step中定义的request、response名称
	 * 4、
	 * @param name
	 * @param flowVarObj
	 */
	public void addFlowVarObj(String name, FlowVarObj flowVarObj) {
		this.allFlowVarObjs.put(name, flowVarObj);
	}

	/**
	 * 调用：1、Flow中定义的全局变量，同Step中的定义变量，只是位置不同
	 * 2、Step中定义的变量，如<var name="PaymentFlag">1</var>
	 * 3、在Script中新定义的变量
	 * @param name
	 * @param variable
	 */
	public void addVar(String name, Object variable) {
		this.allFlowVars.put(name, variable);
	}

	public void init() {

		for (FlowVarObj flowVarObj : allFlowVarObjs.values()) {
			flowVarObj.init(this);
		}
	}
}
